package com.iwhalecloud.bss.kite.cucc.web.service.scene;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionService;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.iwhalecloud.bss.kite.client.api.reception.IServiceOfferService;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneOfferInstService;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneProdInstService;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneService;
import com.iwhalecloud.bss.kite.client.dto.DataResult;
import com.iwhalecloud.bss.kite.client.dto.accept.in.AcceptRequestInDTO;
import com.iwhalecloud.bss.kite.client.dto.cust.ContextCustDTO;
import com.iwhalecloud.bss.kite.client.dto.cust.CustDTO;
import com.iwhalecloud.bss.kite.client.dto.scence.create.request.CreateGiftSceneRequest;
import com.iwhalecloud.bss.kite.client.dto.spec.in.ContractOfferDetailDTO;
import com.iwhalecloud.bss.kite.client.dto.spec.in.OfferRoleDetailDTO;
import com.iwhalecloud.bss.kite.client.vo.scene.ProdRoleModuleVO;
import com.iwhalecloud.bss.kite.client.vo.scene.ProductModuleVO;
import com.iwhalecloud.bss.kite.client.vo.scene.SceneNewOfferVO;
import com.iwhalecloud.bss.kite.client.vo.spec.ServiceOfferVO;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.ExtParamConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.log.KiteLogEnum;
import com.iwhalecloud.bss.kite.common.log.KiteLogger;
import com.iwhalecloud.bss.kite.common.unicode.UnicodeOperTypeKite;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteObjectUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.batch.IBatchOrderNodeService;
import com.iwhalecloud.bss.kite.cucc.client.api.cust.ICustCheckQueryService;
import com.iwhalecloud.bss.kite.cucc.client.api.flow.IFlowService;
import com.iwhalecloud.bss.kite.cucc.client.api.goods.IGoodsService;
import com.iwhalecloud.bss.kite.cucc.client.api.order.ICommonSevice;
import com.iwhalecloud.bss.kite.cucc.client.api.order.IOrderService;
import com.iwhalecloud.bss.kite.cucc.client.api.order.IPrintTemplateService;
import com.iwhalecloud.bss.kite.cucc.client.api.scene.ICuccSceneService;
import com.iwhalecloud.bss.kite.cucc.client.api.scene.IInitSceneOfferInstService;
import com.iwhalecloud.bss.kite.cucc.client.api.shoppingcart.operate.ICuccOperateShoppingCartService;
import com.iwhalecloud.bss.kite.cucc.client.api.shoppingcart.query.ICuccQueryShoppingCartService;
import com.iwhalecloud.bss.kite.cucc.client.dto.cust.CuccContextCustDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.flow.ProcessFlowchartDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.flow.TrackInfoDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.flow.TrackInfoDTO.FlowInfo;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.AttrDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.GoodsDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.inf.InfServContextDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosAcceptStaffDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosAccountDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosAttrDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosContractDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosCustomerDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosDeliveryDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosDiscountDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosGoodsDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosOrderDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosRequestDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosUserDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.scene.CuccCustInfoDTO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.ProcessFlowchartVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.TrackInfoVO;
import com.iwhalecloud.bss.kite.cucc.common.constant.CuccServiceOfferConsts;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalKeyConsts;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalServiceOfferConsts;
import com.iwhalecloud.bss.kite.cucc.common.util.StrTools;
import com.iwhalecloud.bss.kite.cucc.dataservice.cache.CuccOfferKeyAttrCache;
import com.iwhalecloud.bss.kite.cucc.dataservice.cache.CuccOfferOriginalInfoCache;
import com.iwhalecloud.bss.kite.cucc.dataservice.cache.ExtOrderInfoCache;
import com.iwhalecloud.bss.kite.cucc.service.addRoleProdDeal.AddRoleProdFactory;
import com.iwhalecloud.bss.kite.cucc.service.addRoleProdDeal.IAddRoleProdService;
import com.iwhalecloud.bss.kite.cucc.service.batch.BatchAcceptUtil;
import com.iwhalecloud.bss.kite.cucc.service.cache.CuccContextCustCache;
import com.iwhalecloud.bss.kite.cucc.service.goods.GoodsHelper;
import com.iwhalecloud.bss.kite.cucc.service.job.scene.GetMemberUserInfoTaskRh;
import com.iwhalecloud.bss.kite.cucc.service.route.InfServParamUtils;
import com.iwhalecloud.bss.kite.cucc.service.route.InfServRouteFactory;
import com.iwhalecloud.bss.kite.cucc.service.rule.check.Impl.MenuLoadingRuleCompletionService;
import com.iwhalecloud.bss.kite.cucc.service.scene.util.CuccSceneUtil;
import com.iwhalecloud.bss.kite.cucc.service.util.ProdCateUtil;
import com.iwhalecloud.bss.kite.cucc.spec.impl.transfer.GoodsInfoTransfer;
import com.iwhalecloud.bss.kite.cucc.web.controller.scene.SceneController;
import com.iwhalecloud.bss.kite.cucc.web.service.ISceneService;
import com.iwhalecloud.bss.kite.cucc.web.service.accept.vo.InitSceneVO;
import com.iwhalecloud.bss.kite.cucc.web.service.bigdata.util.OppoToSceneUtils;
import com.iwhalecloud.bss.kite.dataservice.cache.AdditionalExtProdCache;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferAttrCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferObjRelRoleCache;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.iwhalecloud.bss.kite.dataservice.entity.KitePageDefine;
import com.iwhalecloud.bss.kite.dataservice.entity.OfferAttr;
import com.iwhalecloud.bss.kite.dataservice.entity.OfferObjRelRole;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.dataservice.util.GeneralSwitchUtils;
import com.iwhalecloud.bss.kite.manager.api.IOperateSceneInstService;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.dto.KiteAttrDTO;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.manager.scene.service.operate.OperateChangeService;
import com.iwhalecloud.bss.kite.manager.transaction.KiteTransactional;
import com.iwhalecloud.bss.kite.manager.util.KiteTransactionUtils;
import com.iwhalecloud.bss.kite.service.context.ServiceContext;
import com.iwhalecloud.bss.kite.web.context.KiteWebContext;
import com.iwhalecloud.bss.kite.web.service.accept.bo.AcceptContext;
import com.iwhalecloud.bss.kite.web.service.accept.bo.SceneModule;
import com.iwhalecloud.bss.kite.web.service.accept.constant.TemplateConsts;
import com.iwhalecloud.bss.kite.web.service.accept.service.SceneModuleCache;
import com.iwhalecloud.bss.kite.web.service.accept.vo.PageNavigationVO;
import com.iwhalecloud.bss.pub.client.constanst.Symbols;
import com.ztesoft.bss.base.staticdata.ServiceOfferConst;
import com.ztesoft.bss.common.bo.LoginInfo;
import com.ztesoft.bss.common.bo.SimpleLoginInfo;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.bss.common.util.StringUtil;
import com.ztesoft.common.logger.api.ZLogger;
import com.ztesoft.common.logger.factory.ZLoggerFactory;

import edu.emory.mathcs.backport.java.util.Collections;

/**
 * 温馨提示:此类过于冗余,禁止再向此类新增逻辑,需要的请新增service;
 */
@Service("cucc.sceneService")
public class SceneService implements ISceneService {

    private static final ZLogger LOGGER = ZLoggerFactory.getLogger(SceneService.class, KeyConsts.LOG_MODULE);

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IOperateSceneInstService operateSceneInstService;

    @Autowired
    private IOperateSceneService operateSceneService;

    @Autowired
    private IQuerySceneInstService querySceneInstService;

    @Autowired
    private ICommonSevice commonService;

    @Autowired
    private IOperateSceneProdInstService operateSceneProdInstService;

    @Autowired
    private IOperateSceneOfferInstService operateSceneOfferInstService;

    @Autowired
    private IGoodsService goodsService;

    @Autowired
    private IServiceOfferService serviceOfferService;

    @Resource(name = "manager.operateChangeService")
    private OperateChangeService operateChangeService;

    @Autowired
    private IInitSceneOfferInstService initSceneOfferInstService;

    @Autowired
    private IPrintTemplateService printTemplateService;

    @Autowired
    private ICommonSevice commonSevice;

    @Autowired
    private ICuccOperateShoppingCartService operateShoppingCartService;

    @Autowired
    private ICuccQueryShoppingCartService queryShoppingCartService;

    @Autowired
    private IFlowService flowService;

    @Autowired
    private ICustCheckQueryService custCheckQueryService;

    @Autowired
    private ICuccSceneService cuccSceneService;

    @SuppressWarnings("unchecked")
    @Override
    public DataResult<String> createOfferSceneByOrderDetailInfo(String orderId, String serviceOfferId, String custId,
        String custName, String staffId, String lanId, String regionId, String operType) {
        Map<String, Object> orderInfo = orderService.getOrderDetail(orderId);
        KitePosDTO kitePosDTO = JSONObject
            .toJavaObject(JSON.parseObject(JSON.toJSONString(orderInfo)), KitePosDTO.class);
        this.initContext(kitePosDTO.getCustomer());
        this.removeActivityGoods(kitePosDTO);
        String serviceOfferIdStr = kitePosDTO.getOrder().getBizType();
        List<String> serviceOfferIdList = KiteListUtils.strToList(",", serviceOfferIdStr);

        String upServiceOfferId = getUpServiceOfferId(serviceOfferIdList, kitePosDTO.getGoods());
        String flowNodeId = KiteMapUtils.getString((Map<String, Object>) orderInfo.get("ORDER"), "FLOW_NODE_ID");
        String nodeCode = "";
        if (KiteStringUtils.isNotEmpty(flowNodeId)) {
            nodeCode = flowNodeId.replaceAll("#.*", "").replaceAll("_release_.*", "");
        }
        LoginInfo loginInfo = ContextUtil.getLoginInfo();
        Map<String, Object> loginExtParams = loginInfo.getUserInfo().getExtParams();
        // 特殊参数,用于创建场景后设置场景参数用,该方法结束前移除
        loginExtParams.put("upServiceOfferId", upServiceOfferId);
        loginExtParams.put("nodeCode", nodeCode);
        String sceneInstId = this.createOfferScene(serviceOfferId, operType, LocalKeyConsts.ASK_SOURCE_ORDER,
            KiteWebContext.getContext().getCustId(), KiteWebContext.getContext().getCust().getCustName(), staffId,
            lanId, regionId, kitePosDTO, null);
        // 回显订单概要信息
        this.queryOrderSummaryInfo(orderId, sceneInstId, kitePosDTO, null, null);
        // 回填A/Z端要求完成时间 公共属性替代
        this.replaceFinishTime(sceneInstId);

        // 场景初始化完成,移除特殊参数
        loginExtParams.remove("upServiceOfferId");
        loginExtParams.remove("nodeCode");

        Map<String, Object> sceneExtParams = this.querySceneInstService.getExtParameter(sceneInstId);
        sceneExtParams.put("orderId", orderId);
        //保存订单信息，用于封装订单信息模块
        sceneExtParams.put("orderInfoMap", orderInfo);
        //保存查到的用户信息节点，调任务完成接口时使用
        sceneExtParams.put("serialNumber", kitePosDTO.getUsers());
        sceneExtParams.put("customer", kitePosDTO.getCustomer());

        if (KiteStringUtils.isNotEmpty(upServiceOfferId)) {
            sceneExtParams.put("BUSI_CHANGE_SERVICEOFFERID", serviceOfferIdList);

            if (LocalServiceOfferConsts.SERVICE_OFFER_FOLLOW.equals(serviceOfferId)) {
                sceneExtParams.put("upServiceOfferId", upServiceOfferId);
            }
        }
        if (!KiteStringUtils.isEmpty(serviceOfferIdStr)) {
            sceneExtParams.put("serviceOfferId", serviceOfferIdStr);
        }

        if (!KiteStringUtils.isEmpty(flowNodeId)) {
            //sceneExtParams.put("nodeCode", flowNodeId.split("#")[0]);
            sceneExtParams.put("nodeCode", nodeCode);
        }

        // 追单、加急、延期等，保存订单来源，提交时订单来源保持不变
        Map<String, Object> request = MapUtils.getMap(orderInfo, "REQUEST");
        KitePosRequestDTO requestDto = new KitePosRequestDTO(request);
        sceneExtParams.put("requestDto", requestDto);

        this.operateSceneInstService.setExtParameter(sceneInstId, sceneExtParams);

        return ErrorConsts.SUCCESS.getResult(sceneInstId);
    }

    @Override
    public DataResult<String> createOfferSceneByWorkOrder(String orderId, String flowId, String taskId,
        String serviceOfferId, String operType, String custId, String custName, String staffId, String lanId,
        String regionId) {
        return createOfferSceneByWorkOrder(orderId, flowId, taskId, serviceOfferId, operType, custId, custName, staffId,
            lanId, regionId, "", null, null);
    }

    @SuppressWarnings({"unchecked", "deprecation"
    })
    @Override
    public DataResult<String> createOfferSceneByWorkOrder(String orderId, String flowId, String taskId,
                                                          String serviceOfferId, String operType, String custId, String custName, String staffId, String lanId,
                                                          String regionId, String orderSource, String toOrderType, String preTaskCode) {
        boolean isAddOrder = false;
        if (KiteStringUtils.isEqual(CuccServiceOfferConsts.SERVICE_OFFER_ADD_ORDER, serviceOfferId)) {
            isAddOrder = true;
        }
        // 获取工单信息
        Map<String, Object> workOrderInfo;
        Map<String, Object> worksheetData;
        KitePosDTO kitePosDTO;
        JSONObject orderData = null;
        Map<String, Object> orderInfo = null;
        List<Map<String, Object>> flowDataList = null;

        if(KiteStringUtils.isEqual(toOrderType, "chargePreCancel")) {
            // 收费方产品-代办发起的预销户操作
            workOrderInfo = cuccSceneService.getOfferSceneDataForChargePreCancel(orderId, flowId, taskId, serviceOfferId, orderSource).getResultObject();
            worksheetData = KiteMapUtils.getMap(workOrderInfo, "worksheetData");
            kitePosDTO = (KitePosDTO) workOrderInfo.get("kitePosDTO");
        } else {
            // 获取工单信息
            InfServContextDTO context = InfServParamUtils.genGetWorkOrder(orderId, flowId, taskId, orderSource);
            workOrderInfo = InfServRouteFactory.getInstance().getWorkOrderInfo(context);
            worksheetData = KiteMapUtils.getMap(workOrderInfo, "worksheetData");
            orderData = (JSONObject) workOrderInfo.get("orderData");

            // 如果有批量标识，根据子单查主单，用主单初始化场景
            if (KiteStringUtils.equalsAny(preTaskCode, "batchSIGN", "batchOrderStartRent")) {
                ServiceContext.setIsBatchAccept(Boolean.TRUE);
                orderInfo = SpringUtil.getBean(IBatchOrderNodeService.class)
                    .getOrderInfoSync(orderId, flowId, preTaskCode, serviceOfferId);
                if (KiteMapUtils.isNotEmpty(orderInfo)) {
                    String rootOrderId = KiteMapUtils.getString(orderInfo, "rootOrderId");
                    Map<String, Object> rootOrderMap = orderService.getOrderDetail(rootOrderId);
                    flowDataList = KiteMapUtils.getValue(rootOrderMap, "FLOW_DATA");
                    KitePosDTO rootKitePos = JSONObject
                        .toJavaObject(JSON.parseObject(JSON.toJSONString(rootOrderMap)), KitePosDTO.class);
                    orderData = JSON.parseObject(JSONObject.toJSONString(rootKitePos));
                }
            }

            // app甩单补录订单详情，若客户id为空，设置一个临时值，否则详情渲染报错
            Map<String, Object> customer = MapUtils.getMap(orderData, "customer");
            if(Objects.isNull(customer)) {
                customer = new HashMap<>();
                orderData.put("customer", customer);
            }
            if(KiteStringUtils.isEmpty(MapUtils.getString(customer, "cbssId"))) {
                customer.put("cbssId", LocalKeyConsts.TEMP_CBSS_ID);
            }
            kitePosDTO = JSONObject.toJavaObject(orderData, KitePosDTO.class);
            if (Objects.nonNull(kitePosDTO.getCustomer())) {
                String cust_id = kitePosDTO.getCustomer().getCbssId();
                kitePosDTO.getCustomer().setCustId(cust_id);
            }
        }

        this.initContext(kitePosDTO.getCustomer());
        this.removeActivityGoods(kitePosDTO);
        //先取映射，取不到直接把bizType作为serviceOfferId
        if (KiteStringUtils.isBlank(serviceOfferId)) {
            serviceOfferId = DcPublicCache.getPCode("20201130001", kitePosDTO.getOrder().getBizType());
        }
        String bizType = kitePosDTO.getOrder().getBizType();
        //支持多场景变更
        List<String> serviceOfferIdList = KiteListUtils.strToList(",", bizType);

        String upServiceOfferId = getUpServiceOfferId(serviceOfferIdList, kitePosDTO.getGoods());
        if (KiteStringUtils.isBlank(serviceOfferId)) {
            if (KiteStringUtils.isEmpty(upServiceOfferId)) {
                serviceOfferId = kitePosDTO.getOrder().getBizType();
            }
            else {
                serviceOfferId = upServiceOfferId;
            }
        }

        if (KiteStringUtils.equals(serviceOfferId, "1")
            && KiteStringUtils.equals("1", KiteMapUtils.getString(worksheetData, "orderSource"))
            && KiteStringUtils.equals(ProdCateUtil.getSingleCateId(ProdCateUtil.MV_CODE), KiteMapUtils.getString(worksheetData, "goodsNodeId"))
            && KiteStringUtils.equals("OrderSigned", KiteMapUtils.getString(worksheetData, "taskCode"))) {
            // MPLS-VPN  核差转定-订单签订
            serviceOfferId = LocalServiceOfferConsts.SERVICE_OFFER_TRANSFER_TO_ORDER;
        }

        //重提标识
        String nodeCode = getNodeCodeByWorkOrder(worksheetData);
        Map<String, Object> loginExtParams = ContextUtil.getLoginInfo().getUserInfo().getExtParams();
        // 特殊参数,用于创建场景后设置场景参数用,该方法结束前移除
        loginExtParams.put("nodeCode", nodeCode);
        loginExtParams.put("serviceOfferId", serviceOfferId);
        loginExtParams.put("goodsNodeId", KiteMapUtils.getString(worksheetData, "goodsNodeId"));
        if(KiteStringUtils.isNotEmpty(KiteMapUtils.getString(worksheetData, "orderData"))){
            JSONObject orderDataObj = JSONObject.parseObject(KiteMapUtils.getString(worksheetData, "orderData"));
            if(orderDataObj.containsKey("exceptionInfo")){
                JSONObject expJson = orderDataObj.getJSONObject("exceptionInfo");
                if(Objects.nonNull(expJson)&&expJson.containsKey("failReason")){
                    loginExtParams.put("BackReason",JSONObject.toJavaObject(expJson, Map.class));
                }
            }
        }
        String sceneInstId = this.createOfferScene(serviceOfferId, operType, LocalKeyConsts.ASK_SOURCE_ORDER,
            KiteWebContext.getContext().getCustId(), KiteWebContext.getContext().getCust().getCustName(), staffId,
            lanId, regionId, kitePosDTO, preTaskCode);
        if (isAddOrder) {
            serviceOfferId = ServiceOfferConst.service_offer_1;
            this.operateSceneInstService.putExtParameter(sceneInstId, "ADDORDER", "T");
        }

        // 回显订单概要信息
        this.queryOrderSummaryInfo(orderId, sceneInstId, kitePosDTO, orderData, worksheetData);
        // 场景扩展参数
        KiteSceneInst sceneInst = this.querySceneInstService.getSceneInst(sceneInstId);
        Map<String, Object> sceneExtParams = this.querySceneInstService.getExtParameter(sceneInstId);
        if (KiteStringUtils.isNotEmpty(upServiceOfferId)) {
            sceneExtParams.put("BUSI_CHANGE_SERVICEOFFERID", serviceOfferIdList);
            sceneInst.setServiceOfferId(serviceOfferId);
        }
        if (KiteStringUtils.isNotEmpty(kitePosDTO.getOrder().getBizType())) {
            sceneInst.setOperType(kitePosDTO.getOrder().getBizType());
        }
        else {
            sceneInst.setOperType(serviceOfferId);
        }
        operateSceneInstService.setSceneInst(sceneInst);
        // 场景初始化完成,移除特殊参数
        loginExtParams.remove("nodeCode");
        loginExtParams.remove("serviceOfferId");
//        loginExtParams.remove("goodsNodeId");
        // 保存订单扩展信息，签订转单需要从中获取taskCode，taskName
        sceneExtParams.put("worksheetId", flowId);

        if(KiteStringUtils.isNotEmpty(toOrderType)) {
            // 收费方预销户补录，调订单归集接口，order节点需要传参数关闭代办，与落地方补录相同，共用落地方补录参数
            sceneExtParams.put("toOrderType", toOrderType);
            sceneExtParams.put("renderOrderType", "orderFallPlace");
            sceneExtParams.put("fallPlaceOrderId", orderId);
            sceneExtParams.put("fallPlaceFlowId", flowId);
        }

        sceneExtParams.put("nodeCode", nodeCode);
        sceneExtParams.put("serviceOfferId", serviceOfferId);
        sceneExtParams.put("orderId", (String) worksheetData.get("orderId"));
        sceneExtParams.put("taskId", (String) worksheetData.get("taskId"));
        sceneExtParams.put("taskCode", (String) worksheetData.get("taskCode"));
        sceneExtParams.put("serialNumber", kitePosDTO.getUsers());
        sceneExtParams.put("customer", kitePosDTO.getCustomer());
        sceneExtParams.put("worksheetData", worksheetData);
        sceneExtParams.put("requestDto", kitePosDTO.getRequest());
        sceneExtParams.put("isTransferOrderScene", "F");
        if (CuccSceneUtil.isTransferOrderSceneByWorkSheetInfo(orderId, kitePosDTO)) {
            sceneExtParams.put("isTransferOrderScene", "T");
        }
        if(KiteStringUtils.isNotEmpty(kitePosDTO.getOrder().getInitiatorOrderId())) {
            sceneExtParams.put("fallPlaceOrderId", kitePosDTO.getOrder().getInitiatorOrderId());
        }
        // 资源核查甩单补录
        if (KiteStringUtils.isEqual(serviceOfferId, "1012") && KiteStringUtils.isEqual(nodeCode, "OrderAddRecord")) {
            sceneExtParams.put("renderOrderType", "orderRejection");
        }
        // 保存订单环节处理信息
        String businessData = (String) worksheetData.get("orderData");
        if (!KiteStringUtils.isEmpty(businessData)) {
            Map<String, Object> orderDataMap = JSONObject.parseObject(businessData, Map.class);
            Map<String, Object> exceptionInfo = (Map<String, Object>) orderDataMap.get("exceptionInfo");
            sceneExtParams.put(LocalKeyConsts.SCENE_EXT_PARAM_EXCEPTION_INFO, exceptionInfo);
        }
        // 保存起租信息
        if (KiteListUtils.isNotEmpty(flowDataList)) {
            sceneExtParams.put("flowData", flowDataList);
        }
        this.operateSceneInstService.setExtParameter(sceneInstId, sceneExtParams);

        return ErrorConsts.SUCCESS.getResult(sceneInstId);
    }

    private String getNodeCodeByWorkOrder(Map<String, Object> worksheetData) {
        // 如果有异常，返回重提编码
        String exceptionType = (String) worksheetData.get("exceptionType");
        if (!KiteStringUtils.isEmpty(exceptionType)) {
            return "OrderResubmit";
        }
        String nodeCodeStr = (String) worksheetData.get("nodeCode");
        if (!KiteStringUtils.isEmpty(nodeCodeStr)) {
            return nodeCodeStr.split("#")[0];
        }
        return "OrderInput";
    }

    @Override
    @KiteTransactional
    public void initContext(KitePosCustomerDTO customer) {
        CuccCustInfoDTO cuccCustInfoDTO = KiteBeanUtils.transform(customer, CuccCustInfoDTO.class);
        CuccContextCustDTO contextCust = new CuccContextCustDTO();
        if (Objects.nonNull(cuccCustInfoDTO)) {
            KiteBeanUtils.copyProperties(cuccCustInfoDTO, contextCust);
            //集团客户名称
            contextCust.setProvinceCode(cuccCustInfoDTO.getEparchyProvince());
            contextCust.setCustName(cuccCustInfoDTO.getName());
            contextCust.setLanId(cuccCustInfoDTO.getEparchyCity());
            contextCust.setEparchyCode(cuccCustInfoDTO.getEparchyCity());
            contextCust.setRegionId(cuccCustInfoDTO.getEparchyArea());
            contextCust.setAttrs(cuccCustInfoDTO.getAttrs());
        }
        ServiceContext.setCust(customer.getCustId(), this.transToCustDTO(contextCust));
        // 根据订单信息（订单详情或工单信息）初始化场景时，在拦截器中获取不到custId，在这里进行处理
        if (!KiteWebContext.getKiteContextId().contains(KiteStringUtils.join(Symbols.HASH, customer.getCustId()))) {
            KiteWebContext.setKiteContextId(KiteStringUtils.joinWith(Symbols.HASH, ContextUtil.getHttpSessoinId(), customer.getCustId()));
        }
        KiteWebContext.initContext(KiteWebContext.getKiteContextId(), contextCust);
        CuccContextCustCache
            .put(ContextUtil.getLoginInfo().getUserInfo().getUserCode(), customer.getCustId(), contextCust);
    }

    @Override
    public CustDTO transToCustDTO(CuccContextCustDTO cuccCustInfoDTO) {
        CustDTO dto = new CustDTO();
        if (Objects.nonNull(cuccCustInfoDTO)) {
            KiteBeanUtils.copyProperties(cuccCustInfoDTO, dto);

            //dto.setProvinceCode(cuccCustInfoDTO.getProvinceCode());
            dto.setLanId(cuccCustInfoDTO.getEparchyCode());
            dto.setRegionId(cuccCustInfoDTO.getRegionId());
            dto.setCustType(cuccCustInfoDTO.getCustClassType());
            dto.setCertiType(cuccCustInfoDTO.getCertiTypeCode());
            dto.setCertiNumber(cuccCustInfoDTO.getCertiCode());
            //dto.setBbssCustId(cuccCustInfoDTO.getBbssCustId());
            //dto.setCbssId(cuccCustInfoDTO.getCustId());
        }
        return dto;
    }

    /**
     * 活动暂不支持，删除goods的活动节点
     *
     * @param kitePosDTO
     */
    private void removeActivityGoods(KitePosDTO kitePosDTO) {
        kitePosDTO.getGoods().removeIf(
            goods -> goods.getProducts().stream().anyMatch(prod -> KiteStringUtils.equals(prod.getType(), "discount")));
    }

    @Override
    @KiteLogger(isWrite = true, type = KiteLogEnum.SERVICE)
    public DataResult<String> createOfferScene(String serialNumber, String prodId, String serviceOfferId, String custId,
        String custName, String staffId, String lanId, String regionId, String userId)  {
        Offer offer = OfferCache.get(prodId);
        Map<String, Object> orderInfo =new HashMap<>();
        KitePosDTO kitePosDTO = null;
        if (Objects.isNull(offer)) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("商品不存在");
        }
        String offerType = offer.getOfferType();

        String provinceId = ContextUtil.getLoginInfo().getUserInfo().getPostProvinceNbr();
        String staffCode = (String) ContextUtil.getLoginInfo().getUserInfo().getExtParams().get("account");
        CompletionService<Map<String,Object>> service = MenuLoadingRuleCompletionService.INSTANCE.getExecutorCompletionService();
        List<Future<Map<String,Object>>> futureList = new ArrayList<>();
        List<KitePosDTO> memKitePosDTOs = Lists.newArrayList();
        if (KiteStringUtils.isEqual(offerType, KeyConsts.OFFER_TYPE_15) ) {
            try {
                GetMemberUserInfoTaskRh callTask = new GetMemberUserInfoTaskRh(provinceId, lanId, staffCode,serialNumber, userId);
                Future<Map<String,Object>> future = service.submit(callTask);
                futureList.add(future);
                for(Future<Map<String,Object>> futures : futureList) {
                    Map<String, Object> returnMap = futures.get();
                    kitePosDTO= (KitePosDTO) returnMap.get("memKitePosDTO");
                    List<Map> memKitePosListDTO = (List) returnMap.get("memKitePosListDTO");
                    for(Map mempos:memKitePosListDTO){
                        KitePosDTO memPos = JSONObject
                            .toJavaObject(JSON.parseObject(JSON.toJSONString(mempos)), KitePosDTO.class);
                        memKitePosDTOs.add(memPos);
                    }
                }
                mergeKitePosDTO(memKitePosDTOs,kitePosDTO);
            } catch (Exception e) {

            }

            // 如果是融合要拼接成员
/*
            mergeKitePosDTO(serialNumber, kitePosDTO);
*/
        }else{
            orderInfo=orderService
                .getChangeOriginOrder(prodId, custId, serialNumber, provinceId, lanId, staffCode, userId);
            kitePosDTO = JSONObject
                .toJavaObject(JSON.parseObject(JSON.toJSONString(orderInfo)), KitePosDTO.class);
        }
        //        this.initContext(kitePosDTO.getCustomer());
        String sceneInstId = this.createOfferScene(serviceOfferId, null, LocalKeyConsts.ASK_SOURCE_USER,
            KiteWebContext.getContext().getCustId(), KiteWebContext.getContext().getCust().getCustName(), staffId,
            lanId, regionId, kitePosDTO, null);

        Map<String, Object> sceneExtParams = this.querySceneInstService.getExtParameter(sceneInstId);
        sceneExtParams.put("serialNumber", kitePosDTO.getUsers());
        sceneExtParams.put("orderId", KiteMapUtils.getString((Map) orderInfo.get("order"), "orderId"));
        sceneExtParams.put(LocalKeyConsts.BUSI_CHANGE_SCENE_ONE, "T");
        sceneExtParams.put(ExtParamConsts.EXT_PARAM_PROD_INST_IDS,
            querySceneInstService.listProdInsts(sceneInstId).stream().map(KiteProdInst::getProdInstId)
                .collect(Collectors.toList()));
        this.operateSceneInstService.setExtParameter(sceneInstId, sceneExtParams);

        return ErrorConsts.SUCCESS.getResult(sceneInstId);
    }

    private void mergeKitePosDTO( List<KitePosDTO> memKitePosDTOs,KitePosDTO kitePosDTO) {
        // 如果是融合要拼接成员
      /*  List<QryGrpMemberDTO> member = new ArrayList<>();
        UserCenterClient userCenterClient = SpringUtil.getBean(UserCenterClient.class);
        QryGrpMemberListByGrpReq qryGrpMemberListByGrpReq = new QryGrpMemberListByGrpReq();
        qryGrpMemberListByGrpReq.setPrimarySerialNumber(serialNumber);
        int curPage = 0;
        final int pageSize = 10;
        qryGrpMemberListByGrpReq.setPageSize(pageSize);

        while (true) {
            qryGrpMemberListByGrpReq.setCurPage(++curPage);
            PageInfo<QryGrpMemberDTO> qryGrpMemberDTOPageInfo = userCenterClient
                .qryGrpMemberListByGrp(qryGrpMemberListByGrpReq);
            List<QryGrpMemberDTO> memberDTOList = qryGrpMemberDTOPageInfo.getList();
            if (KiteListUtils.isEmpty(memberDTOList)) {
                break;
            }
            member.addAll(memberDTOList);
            if (memberDTOList.size() < pageSize) {
                break;
            }
        }

        String provinceId = ContextUtil.getLoginInfo().getUserInfo().getPostProvinceNbr();
        String lanId = ContextUtil.getLoginInfo().getUserInfo().getPostLanId();
        String staffCode = ContextUtil.getLoginInfo().getStaffInfo().getStaffCode();*/
        for(KitePosDTO memKitePosDTO : memKitePosDTOs) {
            if (KiteListUtils.isNotEmpty(memKitePosDTO.getGoods())) {
                List<KitePosGoodsDTO> rootGoods = kitePosDTO.getGoods();
                if (Objects.isNull(rootGoods)) {
                    kitePosDTO.setGoods(new ArrayList<>());
                    rootGoods = kitePosDTO.getGoods();
                }
                rootGoods.addAll(memKitePosDTO.getGoods());
            }

            if (KiteListUtils.isNotEmpty(memKitePosDTO.getUsers())) {
                List<KitePosUserDTO> rootUsers = kitePosDTO.getUsers();
                if (Objects.isNull(rootUsers)) {
                    kitePosDTO.setUsers(new ArrayList<>());
                    rootUsers = kitePosDTO.getUsers();
                }
                rootUsers.addAll(memKitePosDTO.getUsers());
            }

            if (KiteListUtils.isNotEmpty(memKitePosDTO.getDelivery())) {
                List<KitePosDeliveryDTO> rootDelivery = kitePosDTO.getDelivery();
                if (Objects.isNull(rootDelivery)) {
                    kitePosDTO.setDelivery(new ArrayList<>());
                    rootDelivery = kitePosDTO.getDelivery();
                }
                rootDelivery.addAll(memKitePosDTO.getDelivery());
            }

            if (KiteListUtils.isNotEmpty(memKitePosDTO.getContract())) {
                List<KitePosContractDTO> contract = kitePosDTO.getContract();
                if (Objects.isNull(contract)) {
                    kitePosDTO.setContract(new ArrayList<>());
                    contract = kitePosDTO.getContract();
                }
                contract.addAll(memKitePosDTO.getContract());
            }

            if (KiteListUtils.isNotEmpty(memKitePosDTO.getDiscount())) {
                List<KitePosDiscountDTO> discount = kitePosDTO.getDiscount();
                if (Objects.isNull(discount)) {
                    kitePosDTO.setDiscount(new ArrayList<>());
                    discount = kitePosDTO.getDiscount();
                }
                discount.addAll(memKitePosDTO.getDiscount());
            }

            if (KiteListUtils.isNotEmpty(memKitePosDTO.getAccounts())) {
                List<KitePosAccountDTO> accounts = kitePosDTO.getAccounts();
                if (Objects.isNull(accounts)) {
                    kitePosDTO.setAccounts(new ArrayList<>());
                    accounts = kitePosDTO.getAccounts();
                }
                accounts.addAll(memKitePosDTO.getAccounts());
            }
        }


    }

    /**
     * 初始化成员商品（套餐销售品）实例
     *
     * @param sceneInstId
     */
    @Override
    public void initMemberOffers(String sceneInstId, List<ContractOfferDetailDTO> memberOffers) {
        KiteOfferInst mainOfferInst = querySceneInstService.getMainOfferInst(sceneInstId);
        //主商品实例id
        this.operateSceneInstService.putExtParameter(sceneInstId, "mainOfferInstId", mainOfferInst.getOfferInstId());

        if (!KiteListUtils.isEmpty(memberOffers)) {
            for (ContractOfferDetailDTO offer : memberOffers) {
                String key = null;
                if (LocalKeyConsts.ORIGINATOR_ROLE_ID.equals(offer.getRoleId())) {
                    key = "sendOfferInstId";
                }
                else if (LocalKeyConsts.RECEIVER_ROLE_ID.equals(offer.getRoleId())) {
                    key = "receiveOfferInstId";
                }
                else {
                    //附加商品
                    List<OfferAttr> cateIdAttrs = OfferAttrCache.get(offer.getOfferId()).stream()
                        .filter(attr -> KiteStringUtils.equals(attr.getFieldName(), "cateId"))
                        .collect(Collectors.toList());
                    if (!KiteListUtils.isEmpty(cateIdAttrs)) {
                        offer.setRoleId(
                            Optional.ofNullable(cateIdAttrs.get(0)).map(OfferAttr::getDefaultValue).orElse(""));
                    }
                    //key = "addOfferInstId";
                }
                KiteOfferInst memberOfferInst = operateSceneOfferInstService
                    .addOfferInst(sceneInstId, mainOfferInst.getOfferInstId(), offer.getOfferId(), offer.getRoleId(),
                        KiteWebContext.getContext().getCustId(), ContextUtil.getUserId().toString()).getResultObject();
                //String memberOfferInstId = memberOfferInst.getOfferInstId();
                //this.operateSceneInstService.putExtParameter(sceneInstId, key, memberOfferInstId);
                List<KiteAttrDTO> attrs = offer.getAttrs();
                this.updateInstAttr(sceneInstId, attrs, memberOfferInst.getOfferInstId());
            }
        }
    }

    @Override
    public void updateInstAttr(String sceneInstId, List<KiteAttrDTO> attrs, String offerInstId) {
        if (!KiteListUtils.isEmpty(attrs)) {
            for (KiteAttrDTO attr : attrs) {
                operateSceneOfferInstService
                    .updateOfferInstAttr(sceneInstId, offerInstId, attr.getFieldName(), attr.getValue(),
                        attr.getValueDesc(), KiteWebContext.getContext().getCustId(),
                        ContextUtil.getUserId().toString());
                //商品属性选择后对应的产品属性也一致
                List<KiteProdInst> prodInsts = querySceneInstService
                    .listProdInstsFromOfferInst(KiteWebContext.getContext().getCustId(), offerInstId);
                prodInsts.forEach(kiteProdInst -> {
                    operateSceneProdInstService
                        .updateProdInstAttr(sceneInstId, kiteProdInst.getProdInstId(), attr.getFieldName(),
                            attr.getValue(), attr.getValueDesc(), KiteWebContext.getContext().getCustId(),
                            ContextUtil.getUserId().toString(), null);
                });
            }
        }
    }

    @SuppressWarnings("deprecation")
    @Override
    @KiteLogger(isWrite = true, type = KiteLogEnum.SERVICE)
    public String createOfferScene(String serviceOfferId, String operType, String askSource, String custId,
        String custName, String staffId, String lanId, String regionId, KitePosDTO kitePosDTO, String preTaskCode) {

        boolean addOrder = false;
        if (KiteStringUtils.isEqual(CuccServiceOfferConsts.SERVICE_OFFER_ADD_ORDER, serviceOfferId)) {
            addOrder = true;
            serviceOfferId = ServiceOfferConst.service_offer_1;
        }
        LoginInfo loginInfo = ContextUtil.getLoginInfo();
        List<KitePosGoodsDTO> offerInsts = kitePosDTO.getGoods();

        String promotionOfferId = null;
        String catagoryId = null;
        List<String> addRoleOfferIds = new ArrayList<>();
        List<String> singleOfferIds = new ArrayList<>();
        List<String> giftOfferIds = new ArrayList<>();
        List<String> totalOfferIds = new ArrayList<>();
        String giftCatagoryId = "";
        for (KitePosGoodsDTO offerInst : offerInsts) {
            String offerId = offerInst.getCode();
            totalOfferIds.add(offerId);
            if (GoodsHelper.isGift(offerId)) {
                giftOfferIds.add(offerId);
                giftCatagoryId = offerInst.getCatagoryId();
                continue;
            }
            promotionOfferId = offerInst.getSaleGoodsCode();
            if (!GoodsInfoTransfer.isAddRoleOffer(offerId, offerInst.getCatagoryId())) {
                singleOfferIds.add(offerId);
                catagoryId = offerInst.getCatagoryId();
            }
            else {
                addRoleOfferIds.add(offerId);
            }
        }
        if (KiteStringUtils.isNotEmpty(giftCatagoryId)) {
            catagoryId = giftCatagoryId;
        }
        List<OfferRoleDetailDTO> offerRoleDetailList = new ArrayList<>();
        for (String offerId : singleOfferIds) {
            OfferRoleDetailDTO offerRoleDetail = new OfferRoleDetailDTO();
            offerRoleDetail.setOfferId(offerId);
            offerRoleDetailList.add(offerRoleDetail);
        }

        //核查单可能从其它途径过来，SaleGoodsCode不一定有值
        //通过基础商品下的catagoryId去反查
        String sceneInstId = "";
        if (KiteStringUtils.isEmpty(promotionOfferId) && StringUtil.isNotEmpty(catagoryId)) {
            promotionOfferId = getPromotionOfferId(catagoryId, totalOfferIds);
        }

        for (KitePosGoodsDTO offerInst : offerInsts) {
            offerInst.setSaleGoodsCode(promotionOfferId);
            offerInst.setSaleGoodsName(
                Optional.ofNullable(OfferCache.get(promotionOfferId)).map(Offer::getOfferName).orElse(""));
        }

        if (KiteListUtils.isNotEmpty(giftOfferIds)) {
            CreateGiftSceneRequest sceneRequest = new CreateGiftSceneRequest();
            sceneRequest.setCustId(custId);
            sceneRequest.setCustName(custName);
            sceneRequest.setLanId(lanId);
            sceneRequest.setOfferId(giftOfferIds.get(0));
            sceneRequest.setRegionId(ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString());
            sceneRequest.setServiceOfferId(serviceOfferId);
            sceneRequest.setSessionId("-1");
            sceneRequest.setStaffId(ContextUtil.getUserId().toString());

            Map<String, Object> extParams = new HashMap<>();
            extParams.put(KeyConsts.CREATE_GIFT_SCENEINST_WITHOUT_ATTR_LINKAGE, KeyConsts.IFTRUE_T);
            sceneRequest.setExtParams(extParams);
            // 礼包
            sceneInstId = operateSceneService.createGiftSceneInst(sceneRequest).getResultObject();
            // <goods.instanceId, user.serialNumber>
            Map<String, String> serialNumberMap = new HashMap<>();
            List<KitePosUserDTO> users = Optional.ofNullable(kitePosDTO.getUsers()).orElse(new ArrayList<>());
            users.forEach(kitePosUserDTO -> offerInsts.stream().filter(kitePosGoodsDTO -> KiteStringUtils
                .isEqual(kitePosGoodsDTO.getUserInstId(), kitePosUserDTO.getInstanceId())).findFirst()
                .map(KitePosGoodsDTO::getInstanceId)
                .ifPresent(goodInstId -> serialNumberMap.put(goodInstId, kitePosUserDTO.getSerialNumber())));
            operateSceneInstService.putExtParameter(sceneInstId, "serialNumberMap", serialNumberMap);
            operateSceneInstService.putExtParameter(sceneInstId, "instSerialNumberMap", new HashMap<>());

            this.initSceneOfferInstService.initGiftOfferInst(sceneInstId, custId, staffId, offerInsts, loginInfo);
        }
        else {
            //ServiceContext.setIsExecuteAfter(Boolean.FALSE);
            if (KiteListUtils.isNotEmpty(singleOfferIds)) {
                List<String> detailIds = null;
                if (KiteListUtils.isNotEmpty(offerRoleDetailList)) {
                    detailIds = offerRoleDetailList.get(0).getDetailIds();
                }
                sceneInstId = operateSceneService
                    .createOfferSceneInst(serviceOfferId, singleOfferIds.get(0), custId, custName,
                        ContextUtil.getUserId().toString(), lanId,
                        ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString(),
                        String.valueOf(ContextUtil.getLoginInfo().getUserInfo().getExtParams().get("session_id")),
                        detailIds).getResultObject();
                //解决融合子单起租失败重提时,成员商品匹配userInstId为空问题。
                Map<String, String> serialNumberMap = new HashMap<>();
                List<KitePosUserDTO> users = Optional.ofNullable(kitePosDTO.getUsers()).orElse(new ArrayList<>());
                users.forEach(kitePosUserDTO -> offerInsts.stream().filter(kitePosGoodsDTO -> KiteStringUtils
                    .isEqual(kitePosGoodsDTO.getUserInstId(), kitePosUserDTO.getInstanceId())).findFirst()
                    .map(KitePosGoodsDTO::getInstanceId)
                    .ifPresent(goodInstId -> serialNumberMap.put(goodInstId, kitePosUserDTO.getSerialNumber())));
                operateSceneInstService.putExtParameter(sceneInstId, "serialNumberMap", serialNumberMap);
                operateSceneInstService.putExtParameter(sceneInstId, "instSerialNumberMap", new HashMap<>());
            }
            else {
                sceneInstId = operateSceneService
                    .createPromotionOfferSceneInst(serviceOfferId, promotionOfferId, custId, custName, staffId, lanId,
                        regionId, "-1", offerRoleDetailList).getResultObject();
            }
        }
        Map<String, Object> extParams = ContextUtil.getLoginInfo().getUserInfo().getExtParams();
        // 批量受理子单查询详情时，不需要设置上下文
        if (!KiteStringUtils.equals(KiteMapUtils.getString(extParams, "preTaskCode"), "BatchSubOrderDetail")) {
            KiteWebContext.addAndUpdateSceneInstId(sceneInstId);
        }
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        sceneInst.setAskSource(askSource);
        operateSceneInstService.setSceneInst(sceneInst);
        // 增加标识，当前是否为页面初始化渲染（如进入签订页面），忽略 Handler 的属性校验报错，否则会因为属性值校验不通过，导致页面渲染中断
        operateSceneInstService.putExtParameter(sceneInstId, "isInitPageRenderFlag", LocalKeyConsts.IFTRUE_T);

        this.operateSceneInstService.putExtParameter(sceneInstId, "preTaskCode", preTaskCode);
        if (KiteMapUtils.isNotEmpty(extParams) && extParams.containsKey("nodeCode")) {
            this.operateSceneInstService.putExtParameter(sceneInstId, "initSource", "workOrder");
        }
        KitePosOrderDTO order = kitePosDTO.getOrder();
        this.operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.BUSI_CHANGE_SCENE_ONE, "T");
        if (Objects.nonNull(order)) {
            String bizType = Optional.ofNullable(order.getBizType()).orElse("");
            this.operateSceneInstService.putExtParameter(sceneInstId, "bizType", bizType);
        }
        if (addOrder) {
            this.operateSceneInstService.putExtParameter(sceneInstId, "ADDORDER", "T");
        }
        this.operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.ACCEPT_GOODS_SPU, promotionOfferId);
        this.operateSceneInstService.putExtParameter(sceneInstId, "contract", kitePosDTO.getContract());
        // VIK公共属性初始化需要用户状态，开户时间
        this.operateSceneInstService.putExtParameter(sceneInstId, "userInfos", kitePosDTO.getUsers());
        //公共属性初始化,这里仅取出号码给实例属性初始化时使用
        this.initSerialNumberCommonAttr(sceneInstId, kitePosDTO);

        this.initSceneOfferInstService.initMainOfferInst(sceneInstId, custId, staffId, offerInsts, loginInfo);
        // 为了不影响现有功能，对附属产品实例还原，增加了注解实现类，没有注解实现类的，走现有逻辑
        List<KiteOfferInst> mainOfferInsts = this.querySceneInstService.listMainOfferInsts(sceneInstId);
        String catId = Optional.ofNullable(OfferCache.get(mainOfferInsts.get(0).getOfferId())).map(Offer::getCateId)
            .orElse("");
        IAddRoleProdService addRoleProdService = AddRoleProdFactory.getRoleProdSupplier(catId);
        if (Objects.isNull(addRoleProdService)) {
            this.initSceneOfferInstService.initAddRoleOfferInst(sceneInstId, custId, staffId, offerInsts, loginInfo);
        }
        else {
            addRoleProdService.initAddRoleOfferInst(sceneInstId, custId, staffId, offerInsts);
        }

        this.initSceneOfferInstService.initAdditionalOfferInst(sceneInstId, custId, staffId, offerInsts, loginInfo);
        this.initSceneOfferInstService.initOfferInstAcct(sceneInstId, operType, custId, kitePosDTO, loginInfo);
        this.initSceneOfferInstService.initOfferInstContract(sceneInstId, operType, custId, kitePosDTO, loginInfo);
        this.initSceneOfferInstService.initOfferInstDiscount(sceneInstId, operType, custId, kitePosDTO, loginInfo);
        // 变更重提-SIM卡账户间转移-存量迁移需要获取功能产品实例 --12.24
        commonService.initCommonAttrValues(sceneInstId, serviceOfferId, custId, kitePosDTO, loginInfo);
        this.initSceneOfferInstService.initOfferInstDelivery(sceneInstId, operType, custId, kitePosDTO, loginInfo);
        this.initSceneOfferInstService.initSerialNumbers(sceneInstId, operType, custId, kitePosDTO, loginInfo);
        //如果是签订，才放到缓存中--都保存，订单中心会重新生成instanceId，保存也无影响 2020-09-19
        ExtOrderInfoCache.getInst().defaultPut(sceneInstId, kitePosDTO);

        // 初始化完毕，移除 页面初始化渲染 标识
        operateSceneInstService.removeExtParameter(sceneInstId, "isInitPageRenderFlag");

        return sceneInstId;
    }

    private void initSerialNumberCommonAttr(String sceneInstId, KitePosDTO kitePosDTO) {
        InstType instType = this.querySceneInstService.getSceneInst(sceneInstId).getRootInstType();
        if (Objects.equals(InstType.GIFT_OFFER_INST, instType)) {
            List<KitePosUserDTO> mainUsers = kitePosDTO.getUsers().stream()
                .filter(user -> !KiteStringUtils.equals(user.getUserDiffCode(), "-1")).collect(Collectors.toList());
            if (KiteListUtils.isNotEmpty(mainUsers)) {
                // 只有一个主号码
                String serialNumber = mainUsers.get(0).getSerialNumber();
                commonService
                    .setCommonAttrValue(sceneInstId, "business_number", serialNumber, serialNumber, serialNumber);
            }

        }
        else {
            // 业务变更 业务号码回填
            List<KitePosUserDTO> users = kitePosDTO.getUsers();
            if (!KiteListUtils.isEmpty(users)) {
                commonService
                    .setCommonAttrValue(sceneInstId, "business_number", kitePosDTO.getUsers().get(0).getSerialNumber(),
                        kitePosDTO.getUsers().get(0).getSerialNumber(), kitePosDTO.getUsers().get(0).getSerialNumber());
            }
        }
        if (!KiteObjectUtils.isEmpty(kitePosDTO) && KiteListUtils.isNotEmpty(kitePosDTO.getUsers())) {
            commonService.setCommonAttrValue(sceneInstId, "group_user_name", kitePosDTO.getUsers().get(0).getName(),
                kitePosDTO.getUsers().get(0).getName(), kitePosDTO.getUsers().get(0).getName());
        }
    }

    private String getPromotionOfferId(String catagoryId, List<String> offerIds) {
        String promotionOfferId = null;
        List<GoodsDTO> list = goodsService.queryGoodsListInCategroy(catagoryId, null);
        if (KiteListUtils.isNotEmpty(list)) {
            //如果只有1个，默认使用第一个
            if (list.size() == 1) {
                promotionOfferId = list.get(0).getGoodsSku();
            }
            //如果有多个，每个都查一次确认基础商品在哪个促销下面
            else {
                for (GoodsDTO goodsDTO : list) {
                    List<AttrDTO> attrDTOList = CuccOfferKeyAttrCache.get(goodsDTO.getGoodsSku());
                    /*List<AttrDTO> attrDTOList = goodsService.queryGoodKeyAttrs(goodsDTO.getGoodsSku())
                        .getResultObject();*/
                    if (KiteListUtils.isEmpty(attrDTOList)) {
                        // 设备类有多个，但无关键属性
                        Map<String, Object> goodsInfo = CuccOfferOriginalInfoCache.get(goodsDTO.getGoodsSku());
                        //Map<String, Object> goodsInfo = goodsService.queryGoodsByOfferId(goodsDTO.getGoodsSku());
                        List<Map<String, Object>> saleGoods = KiteMapUtils.getValue(goodsInfo, "saleGoods");
                        if (!KiteListUtils.isEmpty(saleGoods)) {
                            for (Map<String, Object> map : saleGoods) {
                                String goodsSku = KiteMapUtils.getString(map, "goodsSku");
                                for (String o : offerIds) {
                                    if (KiteStringUtils.equals(goodsSku, o)) {
                                        promotionOfferId = goodsDTO.getGoodsSku();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else {
                        String goodsSkuList = attrDTOList.get(0).getGoodsSku();
                        for (String o : offerIds) {
                            if (goodsSkuList.contains(o)) {
                                promotionOfferId = goodsDTO.getGoodsSku();
                                break;
                            }
                        }
                    }
                }
            }
        }
        return promotionOfferId;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public DataResult<ProdRoleModuleVO> getProdRoleModuleVO(String roleId, String prodId, String prodInstId,
        String templateId, String offerId) {
        // 1. 组装角色组件
        ProdRoleModuleVO prodRoleModuleVO = new ProdRoleModuleVO();
        prodRoleModuleVO.setProdRoleId(roleId);
        prodRoleModuleVO.setDeleteFlag(TemplateConsts.TRUE_T);
        prodRoleModuleVO.setFreeFlag(TemplateConsts.FALSE_F);

        prodRoleModuleVO.setProdInstId(prodInstId);
        prodRoleModuleVO
            .setAdditionalOfferAdd(AdditionalExtProdCache.getInst().isAdditionalOfferAdd(offerId, prodId, roleId));

        OfferObjRelRole role = OfferObjRelRoleCache.get(roleId);
        if (Objects.nonNull(role)) {
            String roleName = role.getRoleName();
            prodRoleModuleVO.setProdRoleName(roleName);
            prodRoleModuleVO.setModuleName(roleName);
        }

        // 2. 组装产品组件
        ProductModuleVO productModuleVO = new ProductModuleVO();
        productModuleVO.setProdId(prodId);
        productModuleVO.setProdRole(Collections.singletonList(prodRoleModuleVO));

        // 3. 组装场景对象
        SceneNewOfferVO sceneVO = new SceneNewOfferVO();
        sceneVO.setProduct(Collections.singletonList(productModuleVO));

        // 4. 组装场景受理上下文
        AcceptContext acceptContext = new AcceptContext();
        AcceptRequestInDTO dto = new AcceptRequestInDTO();
        dto.setCustId(KiteWebContext.getContext().getCustId());
        dto.setSceneInstId(KiteWebContext.getContext().getCurrentSceneInstId());
        acceptContext.setAcceptRequest(dto);
        acceptContext.setSceneVo(sceneVO);

        // 5. 执行新建成员组件
        String moduleId = TemplateConsts.TEMPLATE_MOVE.equals(templateId) ?
            TemplateConsts.MODULE_MOVE_ADD_ROLE :
            TemplateConsts.MODULE_ADD_ROLE;
        SceneModule sceneModule = SceneModuleCache.get(moduleId, templateId);
        sceneModule.setParentModuleVO(productModuleVO);

        dto.setOfferId(offerId);

        sceneModule.execute(acceptContext);

        return ErrorConsts.SUCCESS
            .getResult(((SceneNewOfferVO) acceptContext.getSceneVo()).getProduct().get(0).getProdRole().get(0));
    }

    /**
     * 配置单打印
     * 新增融合商品配置单打印dealPrintTemplatePlural，原配置单打印未改动见dealPrintTemplateSingular
     */
    @Override
    public Map<String, Object> dealPrintTemplate(String sceneInstId, String serviceOfferId) {
        KiteOfferInst offerInst = querySceneInstService.getGiftOfferInst(sceneInstId);
        ContextCustDTO currentCust = KiteWebContext.getContext().getCust();
        if (offerInst != null && InstType.GIFT_OFFER_INST == offerInst.getInstType()) {
            // 融合产品
            return printTemplateService.dealPrintTemplatePlural(sceneInstId, serviceOfferId, currentCust);
        }
        return printTemplateService.dealPrintTemplateSingular(sceneInstId, serviceOfferId, currentCust);
    }

    private String getUpServiceOfferId(List<String> bizTypes, List<KitePosGoodsDTO> goods) {
        if (KiteListUtils.isEmpty(goods)) {
            return "";
        }
        for (KitePosGoodsDTO offerSpec : goods) {
            String categoryId = Optional.ofNullable(OfferCache.get(offerSpec.getCode())).map(Offer::getCateId)
                .orElse("");
            //只查询主产品
            for (String serviceOfferId : bizTypes) {
                if (!GoodsInfoTransfer.isAddRoleOffer(offerSpec.getCode(), categoryId)) {
                    DataResult<List<ServiceOfferVO>> serviceOfferTypeVOList = serviceOfferService
                        .getUpServiceOffers(categoryId, serviceOfferId);
                    if (KiteListUtils.isEmpty(serviceOfferTypeVOList.getResultObject())) {
                        serviceOfferTypeVOList = serviceOfferService
                            .getUpServiceOffers(offerSpec.getCode(), serviceOfferId);
                    }
                    if (Objects.nonNull(serviceOfferTypeVOList) && KiteListUtils
                        .isNotEmpty(serviceOfferTypeVOList.getResultObject())) {
                        List<ServiceOfferVO> serviceOfferTypeList = serviceOfferTypeVOList.getResultObject();
                        ServiceOfferVO serviceOffer = serviceOfferTypeList.get(0);
                        if (KiteStringUtils.isNotEmpty(serviceOffer.getUpServiceOfferId()) && !KiteStringUtils
                            .isEqual(serviceOffer.getUpServiceOfferId(), "-1")) {
                            return serviceOffer.getUpServiceOfferId();
                        }
                    }
                }
            }
        }
        return "";
    }

    @Override
    public void queryOrderSummaryInfo(String orderId, String sceneInstId, KitePosDTO kitePosDTO, JSONObject orderData, Map<String, Object> worksheetData) {
        //        Map<String, Object> orderInfo = orderService.getOrderDetail(orderId);
        //        KitePosDTO kitePosDTO = JSONObject
        //            .toJavaObject(JSON.parseObject(JSON.toJSONString(orderInfo)), KitePosDTO.class);
        KitePosOrderDTO order = kitePosDTO.getOrder();
        KitePosAcceptStaffDTO accept = kitePosDTO.getAccept();
        if (Objects.nonNull(order) && Objects.nonNull(accept)) {
            String flowNodeId = "";
            if (KiteStringUtils.isNotEmpty(order.getFlowNodeId())) {
                int a = order.getFlowNodeId().indexOf("#");
                if(a > 0) {
                    flowNodeId = order.getFlowNodeId().substring(0, order.getFlowNodeId().indexOf("#"));
                } else {
                    flowNodeId = order.getFlowNodeId().substring(0, order.getFlowNodeId().indexOf("_"));
                }
            }
            // String flowNodeId = order.getFlowNodeId().substring(0, order.getFlowNodeId().indexOf("#"));
            String flowNodeName = order.getFlowNodeName();
            // 订单类型
            String orderType = order.getOrderType();
            String orderTypeName = order.getOrderTypeName();
            // 受理时间
            String acceptDate = order.getOrderDate();
            // 受理部门
            String departmentId = accept.getDepartmentId();
            String departmentName = accept.getDepartmentName();
            // 受理员工
            String staffId = accept.getStaffId();
            String staffName = accept.getName();
            // 订单来源
            commonSevice.setCommonAttrValue(sceneInstId, "ORD10009", "24", "运营平台销售模块", "24");
            // 订单环节
            commonSevice.setCommonAttrValue(sceneInstId, "ORD10006", flowNodeId, flowNodeName, flowNodeId);
            // 订单编号
            commonSevice.setCommonAttrValue(sceneInstId, "ORD10197", orderId, orderId, orderId);
            // 订单类型
            commonSevice.setCommonAttrValue(sceneInstId, "ORD10008", orderType, orderTypeName, orderType);
            // 受理时间
            commonSevice.setCommonAttrValue(sceneInstId, "ACCEPT_DATE", acceptDate, acceptDate, acceptDate);
            // 受理部门
            commonSevice
                .setCommonAttrValue(sceneInstId, "ACCEPT_DEPARTMENT", departmentId, departmentName, departmentId);
            // 受理员工
            commonSevice.setCommonAttrValue(sceneInstId, "ACCEPT_STAFF", staffId, staffName, staffId);
            List<KitePosAttrDTO> orderAttrList = order.getAttrs();
            if (KiteListUtils.isNotEmpty(orderAttrList)) {
                orderAttrList.forEach(orderAttr -> {
                    if (KiteStringUtils.equals(orderAttr.getCode(), LocalKeyConsts.WHOLE_PROCESS_TIME)) {
                        commonSevice
                            .setCommonAttrValue(sceneInstId, LocalKeyConsts.WHOLE_PROCESS_TIME, orderAttr.getValue(),
                                orderAttr.getValue(), orderAttr.getValue());
                    }
                });
            }
        }

        /**
         * 审核任务名称：originTaskName
         * 处理时间：dealDate
         * 审核不通过原因：failReason
         * 处理人：REC_80005
         * 退单类型：REC_100079
         * 退单范围：REC_100080
         */
        if(KiteStringUtils.isNotEmpty(KiteMapUtils.getString(worksheetData, "orderData"))){
            JSONObject orderDataObj = JSONObject.parseObject(KiteMapUtils.getString(worksheetData, "orderData"));
            if(orderDataObj.containsKey("exceptionInfo")){
                JSONObject expJson = orderDataObj.getJSONObject("exceptionInfo");
                if(Objects.nonNull(expJson)){
                    Map exceptionInfo = JSONObject.toJavaObject(expJson, Map.class);
                    String originTaskName = KiteMapUtils.getString(exceptionInfo, "originTaskName");
                    String dealDate = KiteMapUtils.getString(exceptionInfo, "dealDate");
                    String failReason = KiteMapUtils.getString(exceptionInfo, "failReason");
                    commonSevice.setCommonAttrValue(sceneInstId, "originTaskName", originTaskName, originTaskName, originTaskName);
                    commonSevice.setCommonAttrValue(sceneInstId, "dealDate", dealDate, dealDate, dealDate);
                    commonSevice.setCommonAttrValue(sceneInstId, "failReason", failReason, failReason, failReason);
                }
            }
        }
        if(Objects.nonNull(orderData) && orderData.containsKey("flowData")){
            JSONArray flowData = orderData.getJSONArray("flowData");
            if(Objects.nonNull(flowData)&&flowData.size()>0){
                JSONArray flowValue = flowData.getJSONObject(0).getJSONArray("flowValue");
                for (int i = 0; i < flowValue.size(); i++) {
                    JSONObject jsonObject = flowValue.getJSONObject(i);
                    String code = jsonObject.getString("code");
                    if (KiteStringUtils.equalsAny(code, "REC_80005", "REC_100079", "REC_100080")) {
                        String value = jsonObject.getString("value");
                        commonSevice.setCommonAttrValue(sceneInstId, code, value, value, value);
                    }
                }
            }
        }
    }

    private void replaceFinishTime(String sceneInstId) {
        List<KiteProdInst> prodInsts = querySceneInstService.listProdInsts(sceneInstId);
        if (KiteListUtils.isNotEmpty(prodInsts)) {
            prodInsts.forEach(prodInst -> {
                List<KiteAttr> prodInstAttrList = prodInst.listAttrs().stream().filter(
                    instAttr -> ("2_0000122".equals(instAttr.getFieldName()) || "2_0000123"
                        .equals(instAttr.getFieldName()))).collect(Collectors.toList());
                if (KiteListUtils.isNotEmpty(prodInstAttrList)) {
                    prodInstAttrList.forEach(prodInstAttr -> {
                        String originValue = KiteStringUtils.isEmpty(prodInstAttr.getOriginValue()) ?
                            prodInstAttr.getValue() :
                            prodInstAttr.getOriginValue();
                        if ("2_0000122".equals(prodInstAttr.getFieldName())) {
                            commonService
                                .setCommonAttrValue(sceneInstId, LocalKeyConsts.REPLACE_A, prodInstAttr.getValue(),
                                    prodInstAttr.getValueDesc(), originValue);

                        }
                        if ("2_0000123".equals(prodInstAttr.getFieldName())) {
                            commonService
                                .setCommonAttrValue(sceneInstId, LocalKeyConsts.REPLACE_Z, prodInstAttr.getValue(),
                                    prodInstAttr.getValueDesc(), originValue);
                        }
                    });
                }
            });
        }
    }

    @Override
    @KiteTransactional
    public DataResult<InitSceneVO> getInitSceneVODataResult(String cartId, String accNum, String prodId,
        String serviceOfferId, String userId, String flag) {
        boolean addOrderGenNum = false;
        if (KiteStringUtils.isEmpty(serviceOfferId)) {
            serviceOfferId = ServiceOfferConst.service_offer_2826;
        }
        else if (KiteStringUtils.isEqual(CuccServiceOfferConsts.SERVICE_OFFER_ADD_ORDER, serviceOfferId)) {
            addOrderGenNum = true;
        }
        String sceneInstId = this
            .createOfferScene(accNum, prodId, serviceOfferId, "", "", ContextUtil.getUserId().toString(),
                ContextUtil.getLandId(), ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString(), userId)
            .getResultObject();
        if (addOrderGenNum) { // 思路：追加订购（2019）变更业务要求新生成号码,这里加场景标识,确保第一次初始化公共属性的时候生成新号码,后续每次刷页面不生成新号码。
            serviceOfferId = ServiceOfferConst.service_offer_1;
            operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.ADD_ORDE_RGE_NNUM, "T");
            operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.ADD_ORDE, "T");
        }
        KiteSceneInst kiteSceneInst = this.querySceneInstService
            .getSceneInst(sceneInstId, KiteWebContext.getContext().getCustId());
        kiteSceneInst.setOperType(KeyConsts.KITE_SCENE_INST_OPER_TYPE_1000); //业务变更
        kiteSceneInst.setServiceOfferId(serviceOfferId);
        this.operateSceneInstService.createSceneInst(kiteSceneInst);
        setSceneInstId(sceneInstId, cartId, "1008");
        KiteInst inst = querySceneInstService
            .getKiteInst(KiteWebContext.getContext().getCustId(), InstType.MAIN_OFFER_INST,
                kiteSceneInst.getRootInstId());
        if (KiteObjectUtils.isEmpty(inst)) {
            inst = querySceneInstService.getKiteInst(KiteWebContext.getContext().getCustId(), InstType.GIFT_OFFER_INST,
                kiteSceneInst.getRootInstId());
        }
        String offerId = inst.getSpecId();
        Offer offer = OfferCache.get(offerId);
        String cateId = offer.getCateId();
        OppoToSceneUtils.getInst().putOppoMembToContext(cateId,sceneInstId);
        operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.BUSI_CHANGE_SCENE, "T");

        return ErrorConsts.SUCCESS.getResult(new InitSceneVO(offerId, sceneInstId, null, cateId, KiteWebContext.getContext().getCustId()));
    }

    /**
     * 把当前场景添加到购物车，购物车分组状态是：待录入
     *
     * @param sceneInstId
     */
    @Override
    public void cacheShoppingCartGroup(String sceneInstId, String cartId) {
        final String userId = ContextUtil.getUserId().toString();
        final String custId = KiteWebContext.getContext().getCustId();
        final String sessionId = ContextUtil.getHttpSessoinId();
        LoginInfo loginInfo = ContextUtil.getLoginInfo();
        SimpleLoginInfo simpleLoginInfo = ContextUtil.getSimpleLoginInfo();
        if (KiteStringUtils.isEmpty(cartId)) {
            cartId = queryShoppingCartService.getShoppingCartId(userId, custId);
            KiteSceneInst kiteSceneInst = querySceneInstService.getSceneInst(sceneInstId);
            kiteSceneInst.setCartId(cartId);
            operateSceneInstService.setSceneInst(kiteSceneInst);
        }
        String cartStr = cartId;
        CompletableFuture.runAsync(() -> {
            KiteTransactionUtils.beginTransaction();
            try {
                ContextUtil.setHttpSessoinId(sessionId);
                // 兼容接口调用
                ContextUtil.setLoginInfo2LoginInfoThreadLocal(loginInfo);
                ContextUtil.putSimpleLoginInfo2ThreadLocal(simpleLoginInfo);
                operateShoppingCartService
                    .cacheShoppingCartGroup(ContextUtil.getSimpleLoginInfo(), sceneInstId, userId, custId,
                        KeyConsts.SHOPPING_CART_GROUP_STATUS_INPUT, cartStr);
            }
            catch (Exception e) {
                // just log
                LOGGER.error(ErrorConsts.SYSTEM_ERROR.getErrorCode(), e, ErrorConsts.SYSTEM_ERROR.getMsg());
            }
            finally {
                KiteTransactionUtils.commit();
                ContextUtil.removeThreadLocal();
            }
        });
    }

    /**
     * 设值上下文中的场景实例标识
     *
     * @param sceneInstId 场景实例标识
     */
    @Override
    public void setSceneInstId(String sceneInstId, String cartId, String operType) {
        KiteWebContext.addAndUpdateSceneInstId(sceneInstId);

        KiteSceneInst kiteSceneInst = this.querySceneInstService
            .getSceneInst(sceneInstId, KiteWebContext.getContext().getCustId());
        if (KiteStringUtils.isNotEmpty(operType)) {
            kiteSceneInst.setOperType(operType);
        }
        kiteSceneInst.setCartId(cartId);
    }

    @Override
    @KiteTransactional
    public DataResult<InitSceneVO> initOfferSceneByOrderDetailInfo(String orderId, String serviceOfferId,
        String businessType, String cartId, String preTaskCode) {
        // TODO 服务提供和operType需要计算
        String sceneInstId = this
            .createOfferSceneByOrderDetailInfo(orderId, serviceOfferId, "", "", ContextUtil.getUserId().toString(),
                ContextUtil.getLandId(), ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString(),
                KeyConsts.KITE_SCENE_INST_OPER_TYPE_1000).getResultObject();

        KiteSceneInst kiteSceneInst = this.querySceneInstService
            .getSceneInst(sceneInstId, KiteWebContext.getContext().getCustId());
        //kiteSceneInst.setOperType(KeyConsts.KITE_SCENE_INST_OPER_TYPE_1000);
        //kiteSceneInst.setServiceOfferId(serviceOfferId);
        //this.operateSceneInstService.createSceneInst(kiteSceneInst);
        //回执信息
        this.operateSceneInstService.putExtParameter(sceneInstId, "outOrderId", orderId);
        //转单需要原单信息
        this.operateSceneInstService.putExtParameter(sceneInstId, "sourceOrderId", orderId);
        //记录页面URL的TYPE，用于区分业务类型
        this.operateSceneInstService.putExtParameter(sceneInstId, "businessType", businessType);
        // 记录环节标识（其中一种场景是批量受理）
        this.operateSceneInstService.putExtParameter(sceneInstId, "preTaskCode", preTaskCode);

        this.setSceneInstId(sceneInstId, cartId, UnicodeOperTypeKite.OPERTYPE_1001);
        //        ExtOrderInfoCache.getInst().defaultDelete(sceneInstId);

        KiteInst kiteInst = querySceneInstService.getKiteInst(KiteWebContext.getContext().getCustId(), InstType.MAIN_OFFER_INST, kiteSceneInst.getRootInstId());
        if(KiteObjectUtils.isEmpty(kiteInst)){
            kiteInst = querySceneInstService.getKiteInst(KiteWebContext.getContext().getCustId(), InstType.GIFT_OFFER_INST, kiteSceneInst.getRootInstId());
        }
        String offerId = kiteInst.getSpecId();
        Offer offer = OfferCache.get(offerId);
        String cateId = offer.getCateId();
        PageNavigationVO pageNavigationVO = SpringUtil.getBean(SceneController.class)
            .getPageNavigation(serviceOfferId, offer.getOfferType(), offerId, sceneInstId, null, null)
            .getResultObject();
        if (pageNavigationVO == null) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("未配置模板或页面流程,请联系管理员");
        }
        List<KitePageDefine> pageDefineList = new ArrayList<KitePageDefine>();
        // 特殊流程发起  调用接口获取订单中心的重新配置页面流程  只针对双线业务
        if (KiteStringUtils.equalsAny(cateId, ProdCateUtil.getDoubleLineCateIdForArr())) {
            this.OrderProcessFlowchart(orderId, pageNavigationVO);
        }

        if (GeneralSwitchUtils.isSwitchOpened(LocalKeyConsts.ORDER_DETAIL_SWITCH)) {
            //查询订单详情的流程图
            ProcessFlowchartVO flowchartVO = flowService.getProcessFlowchart(orderId, "3");
            if (flowchartVO == null) {
                ErrorConsts.BUSI_COMMON_ERROR.throwOut("未查询到订单页面流程");
            }

            List<ProcessFlowchartDTO> flowchartList = flowchartVO.getFlowchartList();
            if (Objects.nonNull(flowchartList)) {
                for (ProcessFlowchartDTO processFlowchartDTO : flowchartList) {
                    KitePageDefine pageDefine = new KitePageDefine();
                    pageDefine.setStatusCd(LocalKeyConsts.COMMON_STATUS_VALIDATE);
                    pageDefine.setDefineId(String.valueOf(processFlowchartDTO.getSequ()));
                    pageDefine.setName(processFlowchartDTO.getName());
                    pageDefineList.add(pageDefine);
                }
                pageNavigationVO.setPageDefineList(pageDefineList);
            }
        }

        //查询订单当前环节
        if (StrTools.isEqual("1000", serviceOfferId)) {
            TrackInfoVO trackInfoVO = flowService.getOrderProgressInfo(orderId);
            if (Objects.nonNull(trackInfoVO)) {
                TrackInfoDTO trackList = trackInfoVO.getTrackList();
                Map<String, List<FlowInfo>> flowMap = trackList.getFlowInfoList();
                Entry<String, List<FlowInfo>> FlowInfo = flowMap.entrySet().iterator().next();
                String flowName = FlowInfo.getKey();
                pageDefineList = pageNavigationVO.getPageDefineList();
                for (KitePageDefine kitePageDefine : pageDefineList) {
                    if (StrTools.isEqual(kitePageDefine.getName(), flowName)) {
                        kitePageDefine.setPageUrl("/orderDeatils");
                    }
                }
            }
        }
        return ErrorConsts.SUCCESS.getResult(new InitSceneVO(offerId, sceneInstId, pageNavigationVO, cateId, KiteWebContext.getContext().getCustId()));
    }

    @Override
    @KiteTransactional
    public DataResult<InitSceneVO> initOfferSceneByWorkOrder(String orderId, String flowId,
        String taskId,
        String serviceOfferId, String operType, String orderSource, String cartId,
        Map<String, Object> orderInfo, String toOrderType,
        Map<String, Object> dataMap) {

        LoginInfo loginInfo = ContextUtil.getLoginInfo();
        Map<String, Object> loginExtParams = loginInfo.getUserInfo().getExtParams();
        String preTaskCode = KiteMapUtils.getString(loginExtParams, "preTaskCode");
        String sceneInstId = this
            .createOfferSceneByWorkOrder(orderId, flowId, taskId, serviceOfferId, operType, "", "",
                ContextUtil.getUserId().toString(), ContextUtil.getLandId(),
                loginInfo.getUserInfo().getPostRegionId().toString(), orderSource, toOrderType, preTaskCode)
            .getResultObject();

        KiteSceneInst kiteSceneInst = this.querySceneInstService
            .getSceneInst(sceneInstId, KiteWebContext.getContext().getCustId());
        this.setSceneInstId(sceneInstId, cartId, "");
        this.operateSceneInstService.putExtParameter(sceneInstId, "entry", "sceneTempl");
        this.operateSceneInstService.putExtParameter(sceneInstId, "outOrderId", orderId);
        // 增加标识，当前是否为页面初始化渲染（如进入签订页面），忽略 Handler 的属性校验报错，否则会因为属性值校验不通过，导致页面渲染中断
        operateSceneInstService.putExtParameter(sceneInstId, "isInitPageRenderFlag", LocalKeyConsts.IFTRUE_T);

        if (KiteMapUtils.isNotEmpty(orderInfo)) {
            operateSceneInstService.putExtParameter(sceneInstId, "batchOrderInfo", orderInfo);
            List<Map<String, Object>> subOrderList = KiteMapUtils.getValue(orderInfo, "workSheetData");
            if (KiteListUtils.isNotEmpty(subOrderList)
                && !BatchAcceptUtil.isBatchNodeReset(orderId, subOrderList.size(), preTaskCode)) {
                operateSceneInstService.putExtParameter(sceneInstId, "batchNodeResetIsEdit", "F");
                // 设置起租信息
                SpringUtil.getBean(IBatchOrderNodeService.class).restoreRentInfo(sceneInstId);
            }
        }

        operateSceneInstService.putExtParameter(sceneInstId, "preTaskCode", preTaskCode);
        if (KiteStringUtils.equalsAny(preTaskCode, "batchSIGN", "batchOrderStartRent")) {
            String batchNodeCode = querySceneInstService.getExtParameterValue(sceneInstId, "nodeCode");
            operateSceneInstService.putExtParameter(sceneInstId, "nodeCode", "Batch" + batchNodeCode);
            String batchTaskCode = querySceneInstService.getExtParameterValue(sceneInstId, "taskCode");
            operateSceneInstService.putExtParameter(sceneInstId, "taskCode", "Batch" + batchTaskCode);
        }

        String offerId = querySceneInstService
            .getKiteInst(KiteWebContext.getContext().getCustId(), kiteSceneInst.getRootInstType(),
                kiteSceneInst.getRootInstId()).getSpecId();

        if (KiteStringUtils.isEmpty(serviceOfferId)) {
            serviceOfferId = kiteSceneInst.getServiceOfferId();
        }
        Offer offer = OfferCache.get(offerId);
        String cateId = offer.getCateId();
        String finalServiceOfferId = serviceOfferId;
        JSONObject worksheetData = (JSONObject)dataMap.get("worksheetData");
        String provinceCode = worksheetData.getString("provinceCode");
        List<DcPublic> dcPublicList = DcPublicCache.get("202012282032");
        // 将配置了 province 的排在前面
        dcPublicList.sort((t1, t2) -> {
            if(KiteStringUtils.isEmpty(t1.getCodee()) && KiteStringUtils.isNotEmpty(t2.getCodee())) {
                return 1;
            }
            return -1;
        });
        DcPublic dcPublic = dcPublicList.stream()
            .filter(cfg -> KiteStringUtils.equalsAny(cfg.getCodea(), cateId, "-1"))
            .filter(cfg -> KiteStringUtils.equalsAny(cfg.getCodeb(), finalServiceOfferId, "-1"))
            .filter(cfg -> KiteStringUtils.isEmpty(cfg.getCodee()) || KiteStringUtils.isEqual(provinceCode, cfg.getCodee()))
            .findFirst().orElse(null);
        Map result = new HashMap();
        if (!Objects.isNull(dcPublic)) { // 根据不同cateId和serviceOfferId，返回标识给前端，隐藏退单、重提按钮
            result.put("isChargeback", dcPublic.getCodec());
            result.put("isAgain", dcPublic.getCoded());
        }
        // app资源核查甩单补录，没有退单按钮，重提按钮名称改为提交
        String renderOrderType = querySceneInstService.getExtParameterValue(sceneInstId, "renderOrderType");
        if(KiteStringUtils.isEqual(renderOrderType, "orderRejection")) {
            result.put("isChargeback", "T");
            result.put("isAgain", "F");
        }

        // 质检环节标记是否业务变更场景
        if (!KiteStringUtils.equalsAny(operType, "1", "1001")) {
            operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.BUSI_CHANGE_SCENE, "T");
        }
        // 质检过户设置custId
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        if (KiteStringUtils.equals(sceneInst.getServiceOfferId(), ServiceOfferConsts.SERVICE_OFFER_TRANSFER)) {
            // 工单信息返回的custId已经是过户后的custId
            sceneInst.setNewCustId(sceneInst.getCustId());
            operateSceneInstService.setSceneInst(sceneInst);
        }
        PageNavigationVO pageNavigationVO = SpringUtil.getBean(SceneController.class)
            .getPageNavigation(serviceOfferId, offer.getOfferType(), offerId, sceneInstId, null, null)
            .getResultObject();
        if (pageNavigationVO == null) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("未配置模板或页面流程,请联系管理员");
        }

        // 获取订单中心的页面流程
        // 调用接口获取订单中心的重新配置页面流程 只针对双线业务（收费方预销户补录排除，该操作orderId是发起发订单，操作的为收费方预销户补录）
        if (KiteStringUtils.equalsAny(cateId, ProdCateUtil.getDoubleLineCateIdForArr()) && !KiteStringUtils.isEqual(toOrderType, "chargePreCancel")) {
            this.OrderProcessFlowchart(orderId, pageNavigationVO);
        }
        //添加意向客户标识给前端
        String isTransferOrderScene = querySceneInstService.getExtParameterValue(sceneInstId, "isTransferOrderScene");
        String custId = KiteWebContext.getContext().getCustId();
        if(KiteStringUtils.equals(isTransferOrderScene,"T")&&custCheckQueryService.isYxCustType(custId)){
            result.put("userFlag","0");
        }else {
            result.put("userFlag","1");
        }
        OppoToSceneUtils.getInst().putOppoMembToContext(cateId,sceneInstId);

        // 初始化完毕，移除 页面初始化渲染 标识
        operateSceneInstService.removeExtParameter(sceneInstId, "isInitPageRenderFlag");
        return ErrorConsts.SUCCESS.getResult(new InitSceneVO(offerId, sceneInstId, pageNavigationVO, result, cateId, custId));
    }

    // 调用接口获取订单中心的重新配置页面流程  只针对双线业务
    private void OrderProcessFlowchart(String orderId, PageNavigationVO pageNavigationVO) {
        List<KitePageDefine> pageDefineList = new ArrayList<KitePageDefine>();
        ProcessFlowchartVO flowchartVO = flowService.getOrderProcessFlowchart(orderId, "5");
        List<ProcessFlowchartDTO> flowchartList = flowchartVO.getFlowchartList();
        if (Objects.nonNull(flowchartList) && flowchartList.size() > 0) {
            for (ProcessFlowchartDTO processFlowchartDTO : flowchartList) {
                KitePageDefine pageDefine = new KitePageDefine();
                pageDefine.setStatusCd(LocalKeyConsts.COMMON_STATUS_VALIDATE);
                pageDefine.setDefineId(String.valueOf(processFlowchartDTO.getSequ()));
                pageDefine.setName(processFlowchartDTO.getName());
                if (KiteStringUtils.equals(processFlowchartDTO.getStatus(), "EXECUTING")) {
                    pageNavigationVO.getPageDefineList().forEach(pageInfo -> {
                        if (Objects.nonNull(pageInfo) && KiteStringUtils.isNotEmpty(pageInfo.getPageUrl())) {
                            pageDefine.setPageUrl(pageInfo.getPageUrl());
                        }
                    });
                }
                pageDefineList.add(pageDefine);
            }
            pageNavigationVO.setPageDefineList(pageDefineList);
        }
    }

}
